/**
 * 串口功能测试
 * 使用串口0 向电脑发送 hello word；
 * 串口0的引脚：
 * USART0_TX ---> PA9
 * USART0_RX ---> PA10
 * 
 * 使用串口的一般步骤：
 * - 开启时钟（包括串口时钟和GPIO时钟）
 * - 配置GPIO复用模式
 * - 配置GPIO的模式
 * - 配置GPIO的输出
 * - 配置串口（配置串口参数）
 * - 使能串口（串口使能和发送使能）
*/

#include "gd32e23x_rcu.h"
#include "systick.h"
#include "stdio.h"
#include "string.h"


// 主函数：
int main(void) {

    // 初始化 systick
    systick_config();

    // 使能GPIOA 和 串口的端口时钟
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_USART0);

    // 配置GPIO的服用功能，使其为串口功能；
    gpio_af_set(GPIOA, GPIO_AF_1, GPIO_PIN_9);
    gpio_af_set(GPIOA, GPIO_AF_1, GPIO_PIN_10);

    // 配置GPIO 的模式为复用模式
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_9);
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_10);
    // 配置GPIO 的输出
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10);

    // 配置串口
    // 复位串口配置
    usart_deinit(USART0);
    usart_word_length_set(USART0, USART_WL_8BIT);
    usart_stop_bit_set(USART0, USART_STB_1BIT);
    usart_parity_config(USART0, USART_PM_NONE);
    usart_baudrate_set(USART0, 9600);
    usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
    usart_enable(USART0);

    // usart_send_data('h');
    // usart_send_data('e');
    // usart_send_data('l');
    // usart_send_data('l');
    // usart_send_data('o');

    delay_1ms(1000);
    // 发送字符串
    printf("word\n");
    while (1)
    {
        delay_1ms(1000);
        printf("hello word\n");

    }
    

}

/* retarget the gcc's C library printf function to the USART */
#include <errno.h>
#include <sys/unistd.h> // STDOUT_FILENO, STDERR_FILENO

int _read(int file, char *data, int len) {
    // wait until we get a receive interrupt
    while(RESET == usart_flag_get(USART0, USART_FLAG_RBNE))
        ;
    // receive data
    int i = 0;
    data[i++] = (uint8_t) usart_data_receive(USART0);
    // return 1 byte. this really isn't the smartest thing to do
    // (we could wait for more bytes sent after this), 
    // but the upper stdio layer will just again call into
    // this function to read the next byte.
    // we might miss a few bytes though.
    return i;
}

int _write(int file, char *data, int len)
{
    if ((file != STDOUT_FILENO) && (file != STDERR_FILENO))
    {
        errno = EBADF;
        return -1;
    }

    for (int i = 0; i < len; i++)
    {
        usart_data_transmit(USART0, (uint8_t)data[i]);
        while (RESET == usart_flag_get(USART0, USART_FLAG_TBE));
    }

    // return # of bytes written - as best we can tell
    return len;
}

